package cn.mulanbay.admin.api.web.controller;

import cn.mulanbay.admin.api.common.AdminErrorCode;
import cn.mulanbay.admin.api.handler.WxpayHandler;
import cn.mulanbay.admin.api.persistent.service.LoginLogService;
import cn.mulanbay.admin.api.persistent.service.RoleService;
import cn.mulanbay.admin.api.persistent.service.UserService;
import cn.mulanbay.admin.api.persistent.service.UserWxpayInfoService;
import cn.mulanbay.admin.api.web.bean.request.user.*;
import cn.mulanbay.admin.api.web.bean.response.user.UserProfileVo;
import cn.mulanbay.admin.api.web.bean.response.user.UserVo;
import cn.mulanbay.business.bean.LoginUser;
import cn.mulanbay.business.bean.UserLoginInfo;
import cn.mulanbay.business.handler.CacheHandler;
import cn.mulanbay.business.handler.PasswordHandler;
import cn.mulanbay.business.handler.TokenHandler;
import cn.mulanbay.business.util.TreeBeanUtil;
import cn.mulanbay.common.bean.ResultBean;
import cn.mulanbay.common.bean.TreeBean;
import cn.mulanbay.common.exception.ApplicationException;
import cn.mulanbay.common.exception.ErrorCode;
import cn.mulanbay.common.util.BeanCopy;
import cn.mulanbay.common.util.DateUtil;
import cn.mulanbay.common.util.StringUtil;
import cn.mulanbay.persistent.dto.UserRoleDto;
import cn.mulanbay.persistent.entity.*;
import cn.mulanbay.persistent.enums.AuthType;
import cn.mulanbay.persistent.enums.MonitorBussType;
import cn.mulanbay.persistent.enums.UserType;
import cn.mulanbay.web.bean.UserCommonRequest;
import cn.mulanbay.web.controller.BaseController;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户管理
 *
 * @author fenghong
 * @create 2022-01-16 10:00
 */
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

    @Autowired
    UserService userService;

    @Autowired
    RoleService roleService;

    @Autowired
    LoginLogService loginLogService;

    @Autowired
    UserWxpayInfoService userWxpayInfoService;

    @Autowired
    PasswordHandler passwordHandler;

    @Autowired
    CacheHandler cacheHandler;

    @Autowired
    TokenHandler tokenHandler;

    @Autowired
    WxpayHandler wxpayHandler;

    /**
     * 获取用户角色树
     *
     * @param urt
     * @return
     */
    @RequestMapping(value = "/getUserRoleTree")
    public ResultBean getUserRoleTree(UserRoleTreeRequest urt) {
        try {
            List<UserRoleDto> urList = roleService.getUserRoleList(urt.getUserId());
            List<TreeBean> list = new ArrayList<TreeBean>();
            for (UserRoleDto ur : urList) {
                TreeBean tb = new TreeBean();
                tb.setId(ur.getRoleId().toString());
                tb.setText(ur.getRoleName());
                if (ur.getUserRoleId() != null) {
                    tb.setChecked(true);
                }
                list.add(tb);
            }
            Boolean b = urt.getSeparate();
            if (b != null && b) {
                Map map = new HashMap<>();
                map.put("treeData", list);
                List checkedKeys = new ArrayList();
                for (UserRoleDto sf : urList) {
                    if (sf.getUserRoleId() != null) {
                        checkedKeys.add(sf.getRoleId().longValue());
                    }
                }
                map.put("checkedKeys", checkedKeys);
                return callback(map);
            } else {
                return callback(TreeBeanUtil.addRoot(list, urt.getNeedRoot()));
            }
        } catch (Exception e) {
            throw new ApplicationException(ErrorCode.SYSTEM_ERROR, "获取用户角色树异常",
                    e);
        }
    }


    /**
     * 获取用户信息
     *
     * @return
     */
    @RequestMapping(value = "/getProfile", method = RequestMethod.GET)
    public ResultBean getProfile() {
        LoginUser loginUser = tokenHandler.getLoginUserFromRequest(request);
        Long roleId = loginUser.getRoleId();
        Long userId = loginUser.getUserId();
        UserProfileVo ups = new UserProfileVo();
        User user = userService.getById(userId);
        UserSetting us = userService.getUserSetting(userId);
        BeanCopy.copyProperties(user, ups);
        BeanCopy.copyProperties(us, ups);
        if (roleId != null) {
            Role role = roleService.getById(roleId);
            ups.setRoleName(role.getName());
        }
        return callback(ups);
    }

    /**
     * 更新用户信息
     *
     * @return
     */
    @RequestMapping(value = "/editProfile", method = RequestMethod.POST)
    public ResultBean editProfile(@RequestBody @Valid UserProfileRequest upr) {
        User user = userService.getById(upr.getUserId());
        if (upr.getSecAuthType() == AuthType.WECHAT) {
            //检查微信绑定信息
            UserWxpayInfo wx = wxpayHandler.getWxpayInfo(user.getId());
            if (StringUtil.isEmpty(wx.getOpenId())) {
                return callbackErrorCode(AdminErrorCode.USER_SEC_AUTH_WECHAT_NULL_);
            }
        }
        UserSetting us = userService.getUserSetting(upr.getUserId());
        BeanCopy.copyProperties(upr, us);
        user.setLastModifyTime(LocalDateTime.now());
        BeanCopy.copyProperties(upr, user);
        us.setLastModifyTime(LocalDateTime.now());
        userService.updateUser(user, us);
        return callback(null);
    }

    /**
     * 用户自己修改密码
     *
     * @return
     */
    @RequestMapping(value = "/editPassword", method = RequestMethod.POST)
    public ResultBean editPassword(@RequestBody @Valid UserPasswordEditRequest eui) {
        User user = userService.getById(eui.getUserId());
        String pp = passwordHandler.encodePassword(eui.getOldPassword());
        if (!user.getPassword().equals(pp)) {
            return callbackErrorCode(AdminErrorCode.USER_PASSWORD_ERROR);
        }
        String newPP = passwordHandler.encodePassword(eui.getNewPassword());
        user.setPassword(newPP);
        user.setLastModifyTime(LocalDateTime.now());
        userService.updateById(user);
        return callback(null);
    }

    /**
     * 用户自己修改个人信息
     *
     * @return
     */
    @RequestMapping(value = "/editMyInfo", method = RequestMethod.POST)
    public ResultBean editMyInfo(@RequestBody @Valid EditMyInfoRequest eui) {
        User user = userService.getById(eui.getUserId());
        String pp = passwordHandler.encodePassword(eui.getPassword());
        if (!user.getPassword().equals(pp)) {
            return callbackErrorCode(AdminErrorCode.USER_PASSWORD_ERROR);
        }
        if (eui.getSecAuthType() == AuthType.SMS && StringUtil.isEmpty(eui.getPhone())) {
            return callbackErrorCode(AdminErrorCode.USER_SEC_AUTH_PHONE_NULL_);
        }
        if (eui.getSecAuthType() == AuthType.EMAIL && StringUtil.isEmpty(eui.getEmail())) {
            return callbackErrorCode(AdminErrorCode.USER_SEC_AUTH_EMAIL_NULL_);
        }
        if (eui.getSecAuthType() == AuthType.WECHAT) {
            //检查微信绑定信息
            UserWxpayInfo wx = wxpayHandler.getWxpayInfo(user.getId());
            if (StringUtil.isEmpty(wx.getOpenId())) {
                return callbackErrorCode(AdminErrorCode.USER_SEC_AUTH_WECHAT_NULL_);
            }
        }
        UserSetting us = userService.getUserSetting(eui.getUserId());
        user.setUsername(eui.getUsername());
        user.setNickname(eui.getNickname());
        user.setBirthday(eui.getBirthday());
        user.setPhone(eui.getPhone());
        user.setEmail(eui.getEmail());
        user.setSecAuthType(eui.getSecAuthType());
        user.setLastModifyTime(LocalDateTime.now());
        if (!StringUtil.isEmpty(eui.getNewPassword())) {
            // 密码设置
            String encodePassword = passwordHandler.encodePassword(eui.getNewPassword());
            user.setPassword(encodePassword);
        }
        BeanCopy.copyProperties(eui, us);
        us.setLastModifyTime(LocalDateTime.now());
        userService.updateUser(user,us);
        return callback(null);
    }

    /**
     * 获取用户列表
     *
     * @return
     */
    @RequestMapping(value = "/getData", method = RequestMethod.GET)
    public ResultBean getData(@Valid UserSearch sf) {
        Page<User> res = userService.getUserList(sf);
        return callbackDataGrid(res);
    }

    /**
     * 获取详情
     *
     * @return
     */
    @RequestMapping(value = "/get", method = RequestMethod.GET)
    public ResultBean get(Long id) {
       User user = userService.getById(id);
        return callback(user);
    }

    /**
     * 创建
     *
     * @return
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public ResultBean create(@RequestBody @Valid UserFormRequest bean) {
        User user = new User();
        BeanCopy.copyProperties(bean, user);
        // 密码设置
        String encodePassword = passwordHandler.encodePassword(bean.getPassword());
        user.setPassword(encodePassword);
        user.setSecAuthType(bean.getSecAuthType());
        user.setCreatedTime(LocalDateTime.now());
        user.setLevel(3);
        user.setPoints(0);
        UserSetting us = new UserSetting();
        //us.setUserId(user.getId());
        us.setSendEmail(true);
        us.setSendWxMessage(true);
        us.setCreatedTime(LocalDateTime.now());
        userService.createUser(user, us);
        return callback(null);
    }

    /**
     * 修改
     *
     * @return
     */
    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    public ResultBean edit(@RequestBody @Valid UserFormRequest bean) {
        User user = userService.getById(bean.getId());
        String originalPawword = user.getPassword();
        BeanCopy.copyProperties(bean, user);
        String password = bean.getPassword();
        if (null != password && !password.isEmpty()) {
            // 密码设置
            String encodePassword = passwordHandler.encodePassword(bean.getPassword());
            user.setPassword(encodePassword);
        } else {
            user.setPassword(originalPawword);
        }
        user.setLastModifyTime(LocalDateTime.now());
        UserSetting us = userService.getUserSetting(user.getId());
        us.setLastModifyTime(LocalDateTime.now());
        userService.updateUser(user, us);
        return callback(null);
    }

    /**
     * 获取详情
     *
     * @return
     */
    @RequestMapping(value = "/getByUsername", method = RequestMethod.GET)
    public ResultBean getByUsername(String username) {
        User bean = userService.getUserByUsernameOrPhone(username);
        return callback(bean);
    }

    /**
     * 获取角色编号
     *
     * @return
     */
    @RequestMapping(value = "/getRoleId", method = RequestMethod.GET)
    public ResultBean getRoleId(@Valid UserRoleRequest urr) {
        Long roleId = roleService.getUserRoleId(urr.getUserId());
        return callback(roleId);
    }

    /**
     * 更新登录信息
     *
     * @return
     */
    @RequestMapping(value = "/updateLoginInfo", method = RequestMethod.POST)
    public ResultBean updateLoginInfo(@RequestBody @Valid UserLoginInfo bean) {
        User user = userService.getById(bean.getUserId());
        user.setLastLoginIp(bean.getLoginIp());
        user.setLastLoginToken(bean.getLoginToken());
        user.setLastLoginIp(bean.getLoginIp());
        user.setLastLoginTime(bean.getLoginTime());
        user.setLastModifyTime(LocalDateTime.now());

        //增加日志
        LoginLog ll = new LoginLog();
        BeanCopy.copyProperties(bean,ll);
        ll.setCreatedTime(LocalDateTime.now());

        userService.updateLogin(user,ll);
        return callback(null);
    }

    /**
     * 加载登录用户
     *
     * @return
     */
    @RequestMapping(value = "/loadLoginUser", method = RequestMethod.GET)
    public ResultBean loadLoginUser( @Valid LoadLoginUserRequest llu) {
        String loginToken = llu.getLoginToken();
        LoginLog ll = loginLogService.getLoginLog(loginToken);
        //管理员模式不支持(涉及到安全问题)
        if(ll!=null&&ll.getLoginType()!= UserType.ADMIN){
            //此时需要重新设置登录时间，否则会被数据库清理程序清理
            ll.setLoginTime(LocalDateTime.now());
            LoginUser lu = new LoginUser();
            lu.setLoginToken(loginToken);
            lu.setLoginTime(DateUtil.getMills(ll.getLoginTime()));
            User user = userService.getById(ll.getUserId());
            lu.setUser(user);
            if(ll.getLoginType()==UserType.ADMIN){
                //加载角色
                //获取管理员角色信息
                Long roleId = roleService.getUserRoleId(ll.getUserId());
                if(roleId==null){
                    throw new ApplicationException(ErrorCode.USER_ROLE_IS_NULL);
                }
                lu.setRoleId(roleId);
            }
            loginLogService.updateById(ll);
            return callback(lu);
        }
        return callback(null);
    }


    /**
     * 获取用户信息（新版本使用）
     *
     * @return
     */
    @RequestMapping(value = "/getMyInfoWithPerms", method = RequestMethod.GET)
    public ResultBean getMyInfoWithPerms(UserCommonRequest ucr) {
        Long roleId = roleService.getUserRoleId(ucr.getUserId());
        Map map = new HashMap();
        User user = userService.getById(ucr.getUserId());
        UserVo userVo = new UserVo();
        BeanCopy.copyProperties(user,userVo);
        //userVo.setAvatar(mediaHandler.getPictureFullUrl(user.getAvatar()));
        map.put("user", userVo);
        map.put("roles", new String[]{"admin"});
        List<String> perms = roleService.selectRoleFPermsList(roleId);
        map.put("permissions", perms);
        return callback(map);
    }


    /**
     * 获取微信账号
     *
     * @return
     */
    @RequestMapping(value = "/getUserWxpayInfo", method = RequestMethod.GET)
    public ResultBean getUserWxpayInfo(Long userId) {
        UserWxpayInfo uw = wxpayHandler.getWxpayInfo(userId);
        if (uw == null) {
            uw = new UserWxpayInfo();
            uw.setUserId(userId);
        }
        return callback(uw);
    }

    /**
     * 修改用户微信信息
     *
     * @return
     */
    @RequestMapping(value = "/editUserWxpayInfo", method = RequestMethod.POST)
    public ResultBean editUserWxpayInfo(@RequestBody @Valid EditUserWxpayInfoRequest eui) {
        if (eui.getId() == null) {
            UserWxpayInfo uw = new UserWxpayInfo();
            BeanCopy.copyProperties(eui, uw);
            uw.setAppId(wxpayHandler.getAppId());
            uw.setCreatedTime(LocalDateTime.now());
            userWxpayInfoService.saveOrUpdateInfo(uw);
        } else {
            UserWxpayInfo uw = userWxpayInfoService.getById(eui.getId());
            BeanCopy.copyProperties(eui, uw);
            uw.setLastModifyTime(LocalDateTime.now());
            userWxpayInfoService.saveOrUpdateInfo(uw);
        }
        return callback(null);
    }

    /**
     * 获取用户系统监控树
     *
     * @param urt
     * @return
     */
    @RequestMapping(value = "/getSystemMonitorTree")
    public ResultBean getSystemMonitorTree(UserRoleTreeRequest urt) {
        try {
            List<SystemMonitorUser> urList = userService.getSystemMonitorUserList(urt.getUserId());
            List<TreeBean> treeBeans = new ArrayList<>();
            List checkedKeys = new ArrayList();
            for (MonitorBussType sfb : MonitorBussType.values()) {
                if (sfb == MonitorBussType.ALL) {
                    continue;
                }
                TreeBean treeBean = new TreeBean();
                treeBean.setId(String.valueOf(sfb.getValue()));
                treeBean.setText(sfb.getName());
                if (checkMonitorExit(sfb, urList)) {
                    treeBean.setChecked(true);
                    checkedKeys.add(sfb.getValue());
                }
                treeBeans.add(treeBean);
            }
            Boolean b = urt.getSeparate();
            if (b != null && b) {
                Map map = new HashMap<>();
                map.put("treeData", treeBeans);
                map.put("checkedKeys", checkedKeys);
                return callback(map);
            } else {
                return callback(TreeBeanUtil.addRoot(treeBeans, urt.getNeedRoot()));
            }
        } catch (Exception e) {
            throw new ApplicationException(ErrorCode.SYSTEM_ERROR, "获取用户系统监控树异常",
                    e);
        }
    }

    private boolean checkMonitorExit(MonitorBussType v, List<SystemMonitorUser> urList) {
        if (StringUtil.isEmpty(urList)) {
            return false;
        } else {
            for (SystemMonitorUser smu : urList) {
                if (smu.getBussType() == v) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 保存用户监控
     *
     * @return
     */
    @RequestMapping(value = "/saveSystemMonitor", method = RequestMethod.POST)
    public ResultBean saveSystemMonitor(@RequestBody @Valid UserSystemMonitorRequest ur) {
        userService.saveUserSystemMonitor(ur.getUserId(), ur.getBussTypes());
        return callback(null);
    }

}
